#include "contig.h"
#include "gene.h"
#include "bacterialcontigbrowser.h"
#include "../../movingpoint.h"
#include "genomesegment.h"

Contig::Contig( QString cId, BacterialContigBrowser *parent) :
   QGraphicsWidget(parent)
{
    contigId = cId;//this is the label given to the contig.  Eg. species-contigNum
    //qDebug() << "     init contig " << contigId << endl;

    //default height and width values- can be changed later
    height = 100.0;
    width = parent->boundingRect().width();

    //store whether this contig is currently 'on display'
        //this allows the user to hide some contigs
    inBounds = true;

    backgroundColor = new QColor(parent->backgroundColor->red(), parent->backgroundColor->green(), parent->backgroundColor->blue(), parent->backgroundColor->alpha() );
    setupText();//text width, height, font are initialized here

    ntInContig = 0; //num of nt in contig, initially 0, but as genes are added, this value will go up
                    //this is used to keep track of the largest/smallest contigs
                    //so that a universal scale for nt/pixel can be created for all contigs

    setCursor( Qt::ArrowCursor );//make sure arrow cursor is shown over contig

    //not sure if flip is still necessary
        //with code refactoring to genome segment
    flip = false;
    updated = false;//same here- this has to do with movement- may elim

    setAcceptsHoverEvents(true);//when hovering over a contig, make it more prominent
    hovering = false;//currently not hovering


    //setup genome segment- the object that holds a set of genes in a particular configuration
    genomeSegment = new GenomeSegment( this );
    genomeSegment->setPos( widthOfText, boundingRect().y()+height/2.0 ); //positioned after the text in x, in the center of the contig in y
    genomeSegment->setHeight( height );//for now has the same height as the contig
    genomeSegment->setWidth( width - widthOfText );//initial width, will get changed to reflect size in nt of the genomeSegment
    setCacheMode(QGraphicsItem::ItemCoordinateCache);//this call is magic- render to pixmap makes it faster
}



Contig::~Contig()
{
    if( genomeSegment )
        delete genomeSegment;
    if( text )
        delete text;
    if( font )
        delete font;
    if( behindTextRect )
        delete behindTextRect;
}

bool operator< (Contig &c1, Contig &c2)
{
    return c1.contigId.remove("contig").compare( c2.contigId.remove("contig") ) == 1; //c1.genomeSegment->getNTInGenomeSegment() < c2.genomeSegment->getNTInGenomeSegment() ;
}

bool operator<= (Contig &c1, Contig &c2)
{
    return c1.contigId.remove("contig").compare( c2.contigId.remove("contig") ) == 1 ||  c1.contigId.compare( c2.contigId ) == 0;
    //return c1.ntInContig <= c2.ntInContig;
}

bool operator>= (Contig &c1, Contig &c2)
{
    return c1.contigId.remove("contig").compare( c2.contigId.remove("contig") ) == -1 ||  c1.contigId.remove("contig").compare( c2.contigId.remove("contig") ) == 0;
    //return c1.ntInContig >= c2.ntInContig;
}

bool operator> (Contig &c1, Contig &c2)
{
    return c1.contigId.remove("contig").compare( c2.contigId.remove("contig") ) == -1 ;//||  c1.contigId.compare( c2.contigId ) == 0;
    //return c1.ntInContig > c2.ntInContig;
}


void Contig::setupText()
{
    widthOfText = 50;//default width of text value- will get reset from main function
    text = new QGraphicsTextItem( this );
    text->setPlainText( contigId );
    text->setPos(boundingRect().x(), boundingRect().y()+boundingRect().height()/2.0);
    font = new QFont( "Helvetica [Cronyx]", 12);
    font->setPixelSize(13);//setPointSize( 13 );//for now
    textColor = new QColor( 255.0, 255.0, 255.0, 255.0 );
    text->setFont( *font );
    text->setDefaultTextColor ( *textColor );

    text->setZValue( 1000.0 );//make sure text drawn above other elts

    behindTextRect = new QGraphicsRectItem(this);
    behindTextRect->setRect(  boundingRect().x(), boundingRect().y(), widthOfText, boundingRect().height() );
    QBrush b;
    QPen p;
    p.setStyle( Qt::NoPen );
    b.setColor(*backgroundColor );
    b.setStyle( Qt::SolidPattern);
    behindTextRect->setBrush(b);
    behindTextRect->setPen(p);
    behindTextRect->setZValue(900.0);

//    //To align text right ...
//    QTextBlockFormat format
//    format.setAlignment(Qt::AlignRight);
//    QTextCursor cursor = text->textCursor();
//    cursor.select(QTextCursor::Document);
//    cursor.mergeBlockFormat(format);
//    cursor.clearSelection();
//    text->setTextCursor(cursor);
}

int Contig::getMaxTextWidth()
{
    QPainter painter;
    // Set current font
//    font->setPointSize(20);
    painter.setFont(*font);
    QFontMetrics fm = painter.fontMetrics();
    maxTextWidth = fm.width(text->toPlainText());// gives calculated text width with current QFont in QPainter

    return maxTextWidth;
}

void Contig::setTextWidth( int newTextWidth )
{
    widthOfText = newTextWidth;
    genomeSegment->setPos( widthOfText, boundingRect().y()+height/2.0 ); //positioned after the text, in the center of the contig
}

void Contig::addGene( QString geneId, int start, int stop, bool ps)
{
    //keep this, so that bacterial genome browser can setup genome segment width when contig is positioned
    if( stop > ntInContig )//last gene in genomesegment should be where it 'stops'
        ntInContig = stop; //later might be sth else- like an indep value- but this works for now

    genomeSegment->addGene( geneId, start, stop, ps );
}

void Contig::addGene( QString geneId, int start, int stop, bool ps, QString lineOfText, QString fileType )
{
    //keep this, so that bacterial genome browser can setup genome segment width when contig is positioned
    if( stop > ntInContig )//last gene in genomesegment should be where it 'stops'
        ntInContig = stop; //later might be sth else- like an indep value- but this works for now

    genomeSegment->addGene( geneId, start, stop, ps, lineOfText, fileType);
}

void Contig::layoutGenes()
{
    // genes are handled by the genome segment - so layout done here
    genomeSegment->layoutGenes();
}

void Contig::setHeight( float newHeight )
{
    height = newHeight;
    genomeSegment->setHeight( newHeight );//pass down new height to genome segment
}

float Contig::getHeight()
{
    return height;
}

void Contig::setWidth( float newWidth )
{
    width = newWidth;
    //NOTE - genome segment width has to be set separately - because its size is dep on nt in contig
}

float Contig::getWidth()
{
    return width;
}

void Contig::setGenomeSegmentWidth( float newWidth )
{
    genomeSegment->setWidth( newWidth ); //genome segment width is proportional to size, and scaled to size of longest
}

//later may use this function to eliminate some contigs from being drawn
bool Contig::isInBounds( )
{
    return inBounds;
}

int Contig::getNTInContig() const
{
    return ntInContig;
}

//I believe I no longer need these alignment functions...

//alignment functions - will need to be redisigned for the genome segment
void Contig::setDistToMove(QPoint t)
{
    updated = true;
    distToMove = t;
}

//flip function - will be redisigned for the genome segment
void Contig::setFlip( bool f, QPointF rp )
{
    flip = f;
    rotationPt = mapToParent(rp);
}

QStringList Contig::getSelectedGenes()
{
    return genomeSegment->getSelectedGenes();
}

QStringList Contig::getSelectedClusters()
{
    return genomeSegment->getSelectedClusters();
}

bool Contig::containsCluster(QString clusterId)
{
    return genomeSegment->containsCluster(QString clusterId );
}

//--------------------INTERACTION FUNCTIONS -------------------------

//slot for all timer events
//animations controlled here
void Contig::advance()
{
    genomeSegment->advance();
}

void Contig::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    hovering = true;
    setZValue( 10.0 );

    //setHeight( boundingRect().height()*3.0 );

    update();

    //genomeSegment->hoverEventEvent(event);
}

void Contig::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    setZValue( 0.0 );
    hovering = false;

    //setHeight( boundingRect().height()/3.0 );

    update();
}

//-----------------------------CONNECTION FUNCTIONS--------------------
//forge connection between one genome segment and another
void Contig::forgeConnection(Contig *other)
{
    genomeSegment->forgeConnection( other->genomeSegment );
}


//-----------------------------DRAW FUNCTIONS-----------------------
QRectF Contig::boundingRect() const
{
    return QRectF( 0, -height/2.0, width, height);
}

QPainterPath Contig::shape() const
{
    QPainterPath path;
    path.addRect(boundingRect());
    return path;
}


void Contig::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    QRectF bRect = boundingRect();

    //size text according to size of contig
    int textSize = (int) height - 2;
    if( textSize%2 != 0 )
        textSize--;
    if( textSize > 12 )
        textSize = 12;
    if( textSize < 2 )
        textSize = 2;
    if( hovering )
        textSize = 13;

    //font->setPointSize( textSize );//not using set point size anymore- so will work on multi os's
    font->setPixelSize(textSize);
    text->setFont( *font );
    if( hovering )
    {
        text->setZValue(1001.0);
        text->setPos( bRect.x(), bRect.y()+bRect.height()/2.0-text->boundingRect().height()/2.0);//bRect.y()-textSize/2.0);//position at left edge of contig, center of y

        textColor = new QColor( 255.0, 255.0, 255.0, 255.0 );
        text->setDefaultTextColor ( *textColor );
    }
    else
    {
        text->setPos( bRect.x(), bRect.y()+bRect.height()/2.0-text->boundingRect().height()/2.0);//bRect.y()-textSize/2.0);//position at left edge of contig, center of y
        text->setZValue(1000.0);

        textColor = new QColor( 175.0, 175.0, 175.0, 255.0 );
        text->setDefaultTextColor ( *textColor );
    }

    //get width of text with this current font
    painter->setFont( *font );
    QFontMetrics fm = painter->fontMetrics();
    int tw = fm.width(text->toPlainText());// gives calculated text width with current QFont in QPainter

    //draw a line from text to genome segment
    QColor lineColor( 150.0, 150.0, 150.0, 255.0);
    QPen p;
    QBrush b;
    p.setColor( lineColor);
    p.setWidth(1);
    if( hovering )
    {
        p.setWidth( 2 );
        lineColor.setRgb( 255.0, 255.0, 255.0 );
    }
    b.setColor( lineColor );
    painter->setPen( p );
    painter->setBrush(b);
    painter->drawLine( bRect.x()+tw+5, bRect.y()+bRect.height()/2.0, genomeSegment->pos().x()-5, bRect.y()+bRect.height()/2.0);

    if( hovering )
    {
        behindTextRect->setRect(  bRect.x(), bRect.y()+(bRect.height()-12.0)/2.0, tw+5, bRect.height() );//make sure the behind text rect has the right size
    }
    else//note- instead of bRect.y()+(bRect.height()-12.0)/2.0 i intended it to be bRect.y()- but this works better
    {
        behindTextRect->setRect(  bRect.x(), bRect.y()+(bRect.height()-12.0)/2.0, tw+5, 12 );//make sure the behind text rect has the right size
    }

    //painter->drawEllipse((int)(genomeSegment->pos().x()-3), (int)(bRect.y()+bRect.height()/2.0), 6, 6);

}
//------------------------------END DRAW FUNCTIONS--------------------------------
